package breakout2014;

import com.jme3.bounding.BoundingBox;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;


public class BulletControl extends AbstractControl {
    private int screenWidth, screenHeight;
    
    private float speed = 800f;
    public Vector3f direction;
    private Node myRoot;
    private float bulletRadius, magBullet;
    private Vector3f oBullet, dBullet;
    
    public BulletControl(Node root, int screenWidth, int screenHeight) {
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;
        this.myRoot = root;
        this.direction = new Vector3f(0,0,0);
        
    }

    @Override
    protected void controlUpdate(float tpf) {

        bulletRadius = (Float)spatial.getUserData("radius");
        oBullet = spatial.getLocalTranslation();
        dBullet = direction;
        magBullet = speed*tpf;
        String status = (String) spatial.getUserData("status");
        
        //at the beginning place bullet in the middle of the racket    
        if(status.equals("StickOnRacket")) {
            direction.set(0.4f,1,0);
            Spatial racket = myRoot.getChild("racket");
            Vector3f racVec = racket.getLocalTranslation();
            float racHeigth = ((BoundingBox)racket.getWorldBound()).getYExtent();  
            float bullHeigth = ((BoundingBox)spatial.getWorldBound()).getYExtent();  
            spatial.setLocalTranslation(racVec.x,racVec.y+racHeigth+bullHeigth,0);
        }
        //calculate the flight path
        else if(status.equals("InTheAir")) {

             
            handleBorderCollision();
            handleBrickCollision();
            handleOutCollision();
        
            Spatial racket = myRoot.getChild("racket");
            Vector3f racketPos = racket.getLocalTranslation();
            float racketExtX = ((BoundingBox)racket.getWorldBound()).getXExtent();  
            float racketExtY = ((BoundingBox)racket.getWorldBound()).getYExtent();  
            Vector3f oRacket = new Vector3f(0,0,0);
            oRacket.x = racketPos.x-racketExtX;
            oRacket.y = racketPos.y-racketExtY;
            Vector3f dRacket = new Vector3f(1,0,0);
            float magRacket = racketExtX*2;
            
            checkCollisionAlt(oRacket, dRacket, magRacket, oBullet, dBullet, magBullet+bulletRadius, bulletRadius);
            
            spatial.move(direction.mult(magBullet));
        }
    }
            
    protected void handleOutCollision() {
    
        Spatial out = myRoot.getChild("out");
        Vector3f outPos = out.getLocalTranslation();
        float outExtX = ((BoundingBox)out.getWorldBound()).getXExtent();  
        float outExtY = ((BoundingBox)out.getWorldBound()).getYExtent();  
        Vector3f sOut = new Vector3f(0,0,0);
        Vector3f eOut = new Vector3f(0,0,0);
        sOut.x = outPos.x-outExtX;
        sOut.y = outPos.y-outExtY;
        eOut.x = outPos.x+outExtX;
        eOut.y = outPos.y+outExtY;
        LineSegmentIntersection LineIntersector = new LineSegmentIntersection(oBullet, oBullet.add(dBullet.mult(magBullet+bulletRadius)), sOut, eOut);    
        if( LineIntersector.isIntersected()){
            spatial.removeFromParent();
        }
    }

    protected void handleBorderCollision() {
    
        Node borders = (Node)myRoot.getChild("borders");
        for(int index=0;index < borders.getQuantity(); index+=1){
            Spatial border = borders.getChild(index);
            Vector3f borderPos = border.getLocalTranslation();
            float borderExtX = ((BoundingBox)border.getWorldBound()).getXExtent();  
            float borderExtY = ((BoundingBox)border.getWorldBound()).getYExtent();  
            Vector3f sBorder = new Vector3f(0,0,0);
            Vector3f eBorder = new Vector3f(0,0,0);
            sBorder.x = borderPos.x-borderExtX;
            sBorder.y = borderPos.y-borderExtY;
            eBorder.x = borderPos.x+borderExtX;
            eBorder.y = borderPos.y+borderExtY;
            LineSegmentIntersection LineIntersector = new LineSegmentIntersection(oBullet, oBullet.add(dBullet.mult(magBullet+bulletRadius)), sBorder, eBorder);    
            if( LineIntersector.isIntersected()){
                direction = LineIntersector.reflectS1AtS2().normalize();
            }
        }
    }
    
    protected void handleBrickCollision() {
    
        Node bricks = (Node)myRoot.getChild("bricks");
        for(int index=0;index < bricks.getQuantity(); index+=1){
            Spatial brick = bricks.getChild(index);
            Vector3f brickPos = brick.getLocalTranslation();
            float brickExtX = ((BoundingBox)brick.getWorldBound()).getXExtent();  
            float brickExtY = ((BoundingBox)brick.getWorldBound()).getYExtent();  
            
            Vector3f sBrick0 = new Vector3f(brickPos.x-brickExtX,brickPos.y-brickExtY,0);
            Vector3f eBrick0 = new Vector3f(brickPos.x+brickExtX,brickPos.y-brickExtY,0);
            handleCheckBrickCollision(sBrick0, eBrick0, brick);
            Vector3f sBrick1 = new Vector3f(brickPos.x+brickExtX,brickPos.y+brickExtY,0);
            Vector3f eBrick1 = new Vector3f(brickPos.x+brickExtX,brickPos.y-brickExtY,0);
            handleCheckBrickCollision(sBrick1, eBrick1, brick);
            Vector3f sBrick2 = new Vector3f(brickPos.x+brickExtX,brickPos.y+brickExtY,0);
            Vector3f eBrick2 = new Vector3f(brickPos.x-brickExtX,brickPos.y+brickExtY,0);
            handleCheckBrickCollision(sBrick2, eBrick2, brick);
            Vector3f sBrick3 = new Vector3f(brickPos.x-brickExtX,brickPos.y-brickExtY,0);
            Vector3f eBrick3 = new Vector3f(brickPos.x-brickExtX,brickPos.y+brickExtY,0);
            handleCheckBrickCollision(sBrick3, eBrick3, brick);
            
                        
        }
    }
    
    protected void handleCheckBrickCollision(Vector3f sObject, Vector3f eObject, Spatial brick) {
    
        LineSegmentIntersection LineIntersector = new LineSegmentIntersection(oBullet, oBullet.add(dBullet.mult(magBullet+bulletRadius)), sObject, eObject);    
        if( LineIntersector.isIntersected()){
            direction = LineIntersector.reflectS1AtS2().normalize();
            brick.setUserData("hit", true);
        }
    }
    
    
    
    
    
    
    
    protected void checkCollisionAlt(Vector3f oObject, Vector3f dObject, float magRacket, Vector3f oBullet,Vector3f dBullet, float magBullet, float bulletRadius) {
         
        //float magBulletIntercept = (dObject.x*(oBullet.y-oObject.y)-dObject.y*(oBullet.x-oObject.y))/(dBullet.x*dObject.y-dObject.x*dBullet.y);
        //float magRacketIntercept = (oBullet.x + magBulletIntercept * dBullet.x - oObject.x)/dObject.x;
        
            
        //if( ((magBullet+bulletRadius) >= magBulletIntercept) && 
        //     (magBulletIntercept > 0) &&
        //     (magRacket > magRacketIntercept) &&
        //     (magRacketIntercept > 0) ){
        
        LineSegmentIntersection LineIntersector = new LineSegmentIntersection(oBullet, oBullet.add(dBullet.mult(magBullet)), oObject, oObject.add(dObject.mult(magRacket)));    
        if( LineIntersector.isIntersected()){
            //direction = direction.mult(-1);
            direction = LineIntersector.reflectS1AtS2().normalize();
              
            
            //System.out.println("--------------------Schnittpunkt--------------------");
            //System.out.println("oBorder: " + oObject);
            //System.out.println("dBorder: " + dObject);
            //System.out.println("oBullet: " + oBullet);
            //System.out.println("dBullet: " + dBullet);
            //System.out.println("magBullet: " + magBullet);
            //System.out.println("magBulletIntercept: " + magBulletIntercept);
            }
            else{
            }
       
    }
        
        
    

    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {}
}
